import argparse
import os

from dynaconf import Dynaconf

from cover_agent.cover_agent import CoverAgent
from cover_agent.settings.config_loader import get_settings
from cover_agent.settings.config_schema import CoverAgentConfig
from cover_agent.version import __version__


def parse_args(settings: Dynaconf) -> argparse.Namespace:
    """
    Parse command line arguments.
    """
    parser = argparse.ArgumentParser(description=f"Cover Agent v{__version__}")

    # Accepts from environment variables first
    log_db_path = os.getenv("LOG_DB_PATH") or settings.get("log_db_path")

    arg_definitions = [
        ("--source-file-path", dict(type=str, required=True, help="Path to the source file.")),
        ("--test-file-path", dict(type=str, required=True, help="Path to the input test file.")),
        ("--project-root", dict(type=str, default="", help="Path to the root of the project.")),
        (
            "--test-file-output-path",
            dict(
                type=str,
                default="",
                help="Path to the output test file.",
            ),
        ),
        ("--code-coverage-report-path", dict(type=str, required=True, help="Path to the code coverage report file.")),
        (
            "--test-command",
            dict(type=str, required=True, help="The command to run tests and generate coverage report."),
        ),
        (
            "--test-command-dir",
            dict(type=str, default=os.getcwd(), help="The directory to run the test command in. Default: %(default)s."),
        ),
        (
            "--included-files",
            dict(
                type=list,
                default=None,
                nargs="*",
                help=(
                    'List of files to include in the coverage. For example, "--included-files library1.c library2.c." '
                    "Default: %(default)s."
                ),
            ),
        ),
        (
            "--coverage-type",
            dict(
                type=str, default=settings.get("coverage_type"), help="Type of coverage report. Default: %(default)s."
            ),
        ),
        (
            "--report-filepath",
            dict(
                type=str,
                default=settings.get("report_filepath"),
                help="Path to the output report file. Default: %(default)s.",
            ),
        ),
        (
            "--desired-coverage",
            dict(
                type=int,
                default=settings.get("desired_coverage"),
                help="The desired coverage percentage. Default: %(default)s.",
            ),
        ),
        (
            "--max-iterations",
            dict(
                type=int,
                default=settings.get("max_iterations"),
                help="The maximum number of iterations. Default: %(default)s.",
            ),
        ),
        (
            "--max-run-time-sec",
            dict(
                type=int,
                default=settings.get("max_run_time_sec"),
                help=(
                    "Maximum time (in seconds) allowed for test execution. Overrides the value in configuration.toml "
                    "if provided. Default: %(default)s."
                ),
            ),
        ),
        (
            "--additional-instructions",
            dict(
                type=str,
                default="",
                help="Any additional instructions you wish to append at the end of the prompt. Default: %(default)s.",
            ),
        ),
        (
            "--model",
            dict(
                type=str,
                default=settings.get("model"),
                help="Which LLM model to use. Default: %(default)s.",
            ),
        ),
        (
            "--api-base",
            dict(
                type=str,
                default=settings.get("api_base"),
                help="The API url to use for Ollama or Hugging Face. Default: %(default)s.",
            ),
        ),
        (
            "--strict-coverage",
            dict(
                action="store_true",
                help="If set, Cover-Agent will return a non-zero exit code if the desired code coverage is not achieved.",
            ),
        ),
        (
            "--run-tests-multiple-times",
            dict(
                type=int,
                default=settings.get("run_tests_multiple_times"),
                help="Number of times to run the tests generated by Cover Agent. Default: %(default)s.",
            ),
        ),
        (
            "--log-db-path",
            dict(type=str, default=log_db_path, help="Path to optional log database. Default: %(default)s."),
        ),
        (
            "--branch",
            dict(
                type=str,
                default=settings.get("branch"),
                help="The branch to compare against when using --diff-coverage. Default: %(default)s.",
            ),
        ),
        ("--run-each-test-separately", dict(action="store_true", help="Run each test separately.")),
        ("--record-mode", dict(action="store_true", help="Enable record mode for LLM responses. Default: False.")),
        (
            "--suppress-log-files",
            dict(action="store_true", help="Suppress all generated log files (HTML, logs, DB files)."),
        ),
    ]

    for name, kwargs in arg_definitions:
        parser.add_argument(name, **kwargs)

    # Create mutually exclusive group
    group = parser.add_mutually_exclusive_group()
    group.add_argument(
        "--use-report-coverage-feature-flag",
        action="store_true",
        help=(
            "Setting this to True considers the coverage of all the files in the coverage report. This means "
            "we consider a test as good if it increases coverage for a different file other than the source file. "
            "Default: False. Not compatible with --diff-coverage."
        ),
    )
    group.add_argument(
        "--diff-coverage",
        action="store_true",
        help=(
            "If set, Cover-Agent will only generate tests based on the diff between branches. Default: False. "
            "Not compatible with --use-report-coverage-feature-flag."
        ),
    )

    return parser.parse_args()


def main():
    settings = get_settings().get("default")
    args = parse_args(settings)
    config = CoverAgentConfig.from_cli_args_with_defaults(args)
    agent = CoverAgent(config)
    agent.run()


if __name__ == "__main__":
    main()
